package com.jinhongone.pattern.structure.proxy.cglibProxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyFactory {

    private Object target;

    public CglibProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        //说明：cglib动态代理是通过继承目标对象，所以目标对象是父类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        //此处有2种写法：1种是类实现MethodInterceptor接口，重写intercept方法，setCallback(this)，直接放当前对象；
        //第二种就是使用匿名内部类的方式实现(如下)
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * 代理对象增强方法
             * @param o 代理对象
             * @param method 目标类原方法
             * @param objects 调用方法的实参
             * @param methodProxy cglib提供的工具类，代理对象的方法
             * @return 方法调用后的返回
             * @throws Throwable
             */
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //method和methodProxy的区别：method是目标类的方法，methodProxy是cglib提供的工具类，是代理对象的方法，可以通过methodProxy工具类更高效的调用父类(目标类)的原方法
                //调用父类原方法，method和methodProxy都可以，但method采用反射，methodProxy采用字节码效率更高
                System.out.println("cglib-动态代理生成代理对象（前置增加逻辑）");
                //通过methodProxy调用父类原方法，由于是调用父类方法，所以参数中传入的是o：代理对象（子类实例），而不是target（父类实例），
                //使用target作用参数，作为调用对象，调用父类方法会报错
                Object result = methodProxy.invokeSuper(o, objects);
                System.out.println("cglib-动态代理生成代理对象（后置增加逻辑）");
                return result;
            }
        });
        return enhancer.create();
    }
}
